package com.bwie.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.mapper.TbMenuMapper;
import com.bwie.pojo.TbMenu;
import com.bwie.pojo.TbUser;
import com.bwie.service.TbUserService;
import com.bwie.mapper.TbUserMapper;
import com.bwie.utils.MobileMessageUtil;
import com.bwie.utils.R;
import com.bwie.vo.LoginVo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.apache.bcel.classfile.Code;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.rmi.MarshalledObject;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* @author 31439
* @description 针对表【tb_user(用户表)】的数据库操作Service实现
* @createDate 2025-07-18 14:06:51
*/
@Service
@Slf4j
public class TbUserServiceImpl extends ServiceImpl<TbUserMapper, TbUser>
    implements TbUserService{

    @Autowired
    TbUserMapper tbUserMapper;
    @Autowired
    TbMenuMapper tbMenuMapper;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    HttpServletRequest request;

    @Override
    public R sendCode(String mobile) {
        //生成验证码
        String code = RandomUtil.randomNumbers(4);
        log.info("code="+code);
        //存redis

        String key = "code-"+mobile;
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //发送验证码
        MobileMessageUtil.sendMobileMessage(mobile,code);
        return R.OK(code);
    }

    @Override
    public R enrollUser(LoginVo loginVo) {
        //判断用户存不存在
        TbUser tbUser = tbUserMapper.selectOne(new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserMobile, loginVo.getMobile()));
        if(tbUser != null){
            return R.ERROR(500,"该用户已注册");
        }
        //验证验证码
       String key = "code-"+loginVo.getMobile();
        String redisCode = redisTemplate.opsForValue().get(key);
        if(redisCode == null){
            return R.ERROR(500,"验证码已过期");
        }
        if(!redisCode.equals(loginVo.getCode())){
            return R.ERROR(500,"验证码错误");
        }
        //加密密码
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String hashPass = encoder.encode(loginVo.getPassWord());
        log.info("加密前密码为:"+loginVo.getPassWord());
        log.info("加密后密码为:"+hashPass);

        //注册用户
        tbUser = new TbUser();
        tbUser.setUserName("匿名用户");
        tbUser.setUserMobile(loginVo.getMobile());
        tbUser.setUserPass(hashPass);
        tbUser.setCreatedTime(new Date());
        tbUserMapper.insert(tbUser);
        return R.OK();
    }

    @Override
    public R userLogin(LoginVo loginVo) {
        //判断用户是否存在
        TbUser tbUser = tbUserMapper.selectOne(new QueryWrapper<TbUser>().lambda().eq(TbUser::getUserMobile, loginVo.getMobile()));
        if(tbUser == null){
            return R.ERROR(500,"该用户未注册");
        }
        //判断验证码是否正确
        String key = "code-"+loginVo.getMobile();
        String redisCode = redisTemplate.opsForValue().get(key);
        if(redisCode == null){
            return R.ERROR(500,"验证码已失效");
        }
        if(!redisCode.equals(loginVo.getCode())){
            return R.ERROR(500,"验证码错误");
        }
        //判断密码是否正确
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        boolean check = encoder.matches(loginVo.getPassWord(), tbUser.getUserPass());
        if(!check){
            return R.ERROR(500,"密码错误");
        }

        //生成token
        String token = Jwts.builder().signWith(SignatureAlgorithm.HS256, "123456").claim("userId", tbUser.getUserId()).compact();

        String keys = "token-"+tbUser.getUserId();
        //存token
        redisTemplate.opsForValue().set(keys,token,60,TimeUnit.MINUTES);

        //获取当前用户角色
        List<String> roleList = tbUserMapper.getRoleListByUserId(tbUser.getUserId());
        tbUser.setRoleList(roleList);

        //返回值
        tbUser.setUserPass(null);
        tbUser.setToken(token);

        return R.OK(tbUser);
    }

    @Override
    public R getMenuTree() {
        //从token中解析出来userId
        String token = request.getHeader("token");
        if(token == null) {
            return R.ERROR(500, "请先登录");
        }

        //获取userId
        Claims body = Jwts.parser().setSigningKey("123456").parseClaimsJws(token).getBody();
        Integer userId = body.get("userId", Integer.class);


        //根据用户ID获取权限列表
        List<TbMenu> menuList = tbMenuMapper.getMenuTree(userId);

        //把用户的权限封装到菜单树
        List<Tree<String>> menuTree = TreeUtil.build(menuList, "0", (menu, tree) -> {
            tree.setId("" + menu.getMenuId());
            tree.setParentId("" + menu.getMenuPid());
            tree.setName(menu.getMenuName());
            tree.putExtra("menuPath", menu.getMenuPath());
        });

        return R.OK(menuTree);
    }


}




